package com.gpframework.module.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.gpframework.common.core.domain.AjaxResult;
import com.gpframework.common.core.domain.entity.SysDept;
import com.gpframework.common.core.domain.entity.SysUser;
import com.gpframework.common.enums.DestinationTypeEnum;
import com.gpframework.common.enums.OrderCharacteristicsEnum;
import com.gpframework.common.enums.OrderStatusEnum;
import com.gpframework.common.enums.YesNoEnum;
import com.gpframework.common.utils.DateUtils;
import com.gpframework.common.utils.StringUtils;
import com.gpframework.module.order.domain.*;
import com.gpframework.module.order.domain.req.GpOrderFlowUpdate;
import com.gpframework.module.order.domain.vo.*;
import com.gpframework.module.order.service.*;
import com.gpframework.module.system.mapper.SysDeptMapper;
import com.gpframework.module.system.mapper.SysUserMapper;
import com.gpframework.module.system.mapper.SysUserRoleMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gpframework.module.order.mapper.GpOrderFlowMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName GpOrderFlow
 * @Author gpframework
 * @Date 2023-06-16
 * @Version 1.0.0
 * @Description 员工订单流转详情Service业务层处理
 */
@Service
public class GpOrderFlowServiceImpl extends ServiceImpl<GpOrderFlowMapper, GpOrderFlow> implements IGpOrderFlowService {

    @Autowired
    private IGpFlowConfigService gpFlowConfigService;
    @Autowired
    private IGpOrderService gpOrderService;
    @Autowired
    private IGpFlowConfigRoleRelaService gpFlowConfigRoleRelaService;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private IGpOrderNotifyService gpOrderNotifyService;
    @Autowired
    private IGpDestinationNoConfigService gpDestinationNoConfigService;
    @Autowired
    private IGpDestinationNoLogService gpDestinationNoLogService;

    /**
     * @Description 查询列表返回VO 用于返回给前端的列表接口
     * @Author gpframework
     * @Date 2023-06-16
     * @Param [lqw]
     * @Return List<GpOrderFlowVo>
     */
    @Override
    public List<GpOrderFlowVo> listVo(QueryWrapper<GpOrderFlow> lqw) {
        return this.baseMapper.listVo(lqw);
    }

    /**
     * @Description 通过查询详情VO 用于返回给前端的列详情接口
     * @Author gpframework
     * @Date 2023-06-16
     * @Param [id]
     * @Return GpOrderFlowVo
     */
    @Override
    public GpOrderFlowVo getVoById(Long id) {
        return this.baseMapper.getVo(id);
    }

    @Override
    @Transactional
    public String confirm(GpOrderFlowUpdate gpOrderFlowUpdate) {
        StringBuilder returnStr = new StringBuilder();
        GpOrder gpOrder;
        GpOrderFlow orderFlow;
        GpFlowConfig flowConfig;
        Date inletTime;
        Date now = new Date();
        // 查看当前用户所有的权限（角色）
        List<Long> roleList = sysUserRoleMapper.getroleIdListByUserId(gpOrderFlowUpdate.getUserId().toString());
        List<GpFlowConfigRoleRelaVo> flowConfigRoleRelaList;
        List<Long> configRoleList;
        Boolean isComplete;
        UpdateWrapper<GpOrder> orderUpdateLqw;
        for (Long id : gpOrderFlowUpdate.getIds()) {
            flowConfig = null;
            // 获取订单信息
            gpOrder = gpOrderService.getById(id);
            isComplete = false;
            if (gpOrder == null || StringUtils.equals(gpOrder.getOrderStatus(), OrderStatusEnum.COMPLETE.getKey())) {
                // 订单不存在或完成，跳过当前订单
                continue;
            }
            if (StringUtils.equals(gpOrder.getIsException().toString(), YesNoEnum.YES.getKey()) && !StringUtils.equals(gpOrder.getExceptionType(), "今日到货")) {
                // 订单状态异常，无法进行流程流转
                returnStr.append("订单").append(gpOrder.getFormCode()).append("异常，请联系录入人员进行操作;");
                continue;
            }
            orderUpdateLqw = new UpdateWrapper<>();
            orderUpdateLqw.set("version", gpOrder.getVersion() + 1).eq("version", gpOrder.getVersion()).eq("id", gpOrder.getId());
            if (StringUtils.equals(gpOrder.getIsException().toString(), YesNoEnum.YES.getKey())) {
                // 如果订单状态从异常改成正常，记录暂停结束时间和暂停时长
                gpOrder.setSuspendEndTime(now);
                gpOrder.setSuspendDuration(DateUtils.getDateMinDiff(now, gpOrder.getSuspendStartTime()));
                orderUpdateLqw.set("suspend_start_time", null);
                orderUpdateLqw.set("suspend_end_time", null);
                orderUpdateLqw.set("suspend_duration", 0);
                if (!StringUtils.equals(gpOrder.getExceptionType(), "今日到货")) {
                    orderUpdateLqw.set("exception_type", null);
                }
                orderUpdateLqw.set("is_exception", 0);
            }
            String orderStatus = gpOrder.getOrderStatus();
            // 如果是待发货或待中转，并且没传车次去向，则返回报错
            if ((StringUtils.equals(orderStatus, OrderStatusEnum.TO_BE_SEND_OUT_GOODS.getKey())
                    || StringUtils.equals(orderStatus, OrderStatusEnum.TO_BE_TRANSFER.getKey()))
                    && StringUtils.isBlank(gpOrderFlowUpdate.getDestinationType())){
                returnStr.append("订单").append(gpOrder.getFormCode()).append("未传车次、车号，无法进行操作;");
                continue;
            }
            if (StringUtils.equals(orderStatus, OrderStatusEnum.TO_BE_PICKING_UP_GOODS.getKey())) {
                // 拿货
                flowConfig = gpFlowConfigService.getOne(new QueryWrapper<GpFlowConfig>().eq("sort", OrderStatusEnum.PICKING_UP_GOODS.getKey()).orderByAsc("sort").last("limit 1"));
                if (StringUtils.equals(gpOrder.getOrderCharacteristics(), OrderCharacteristicsEnum.LOOSE_SHEAR.getKey())) {
                    // 散剪，到待发货
                    orderUpdateLqw.set("order_status", OrderStatusEnum.TO_BE_SEND_OUT_GOODS.getKey());
                } else {
                    // 大货
                    if (gpOrder.getIsInspection() == 1) {
                        // 如果需要验货，跳转到验货
                        orderUpdateLqw.set("order_status", OrderStatusEnum.TO_BE_INSPECTION.getKey());
                    } else {
                        // 不需要验货，跳转到待备货
                        orderUpdateLqw.set("order_status", OrderStatusEnum.TO_BE_STOCK_UP.getKey());
                    }
                }
            } else if (StringUtils.equals(orderStatus, OrderStatusEnum.TO_BE_INSPECTION.getKey())) {
                // 验货（待备货）
                flowConfig = gpFlowConfigService.getOne(new QueryWrapper<GpFlowConfig>().eq("sort", OrderStatusEnum.INSPECTION.getKey()).orderByAsc("sort").last("limit 1"));
                orderUpdateLqw.set("order_status", OrderStatusEnum.TO_BE_STOCK_UP.getKey());
            } else if (StringUtils.equals(orderStatus, OrderStatusEnum.TO_BE_STOCK_UP.getKey())) {
                // 备货（待发货）
                flowConfig = gpFlowConfigService.getOne(new QueryWrapper<GpFlowConfig>().eq("sort", OrderStatusEnum.STOCK_UP.getKey()).orderByAsc("sort").last("limit 1"));
                orderUpdateLqw.set("order_status", OrderStatusEnum.TO_BE_SEND_OUT_GOODS.getKey());
            } else if (StringUtils.equals(orderStatus, OrderStatusEnum.TO_BE_SEND_OUT_GOODS.getKey())) {
                // 发货
                flowConfig = gpFlowConfigService.getOne(new QueryWrapper<GpFlowConfig>().eq("sort", OrderStatusEnum.SEND_OUT_GOODS.getKey()).orderByAsc("sort").last("limit 1"));
                if (StringUtils.equals(gpOrderFlowUpdate.getDestinationType(), DestinationTypeEnum.TRANSIT_WAREHOUSE.getKey())) {
                    // 中转(待中转)
                    orderUpdateLqw.set("order_status", OrderStatusEnum.TO_BE_TRANSFER.getKey());
                } else {
                    // 发货（完成）
                    orderUpdateLqw.set("order_status", OrderStatusEnum.COMPLETE.getKey());
                    isComplete = true;
//                    orderUpdateLqw.set("order_duration", DateUtils.getDateMinDiff(now, gpOrder.getCreateTime()));
                }
            } else if (StringUtils.equals(orderStatus, OrderStatusEnum.TO_BE_TRANSFER.getKey())) {
                // 中转（完成）
                flowConfig = gpFlowConfigService.getOne(new QueryWrapper<GpFlowConfig>().eq("sort", OrderStatusEnum.TRANSFER.getKey()).orderByAsc("sort").last("limit 1"));
                if (StringUtils.equals(gpOrderFlowUpdate.getDestinationType(), DestinationTypeEnum.LOGISTICS.getKey())) {
                    // 如果选择物流，需要流转至‘中转送货中’
                    orderUpdateLqw.set("order_status", OrderStatusEnum.IN_TRANSIT_DELIVERY.getKey());
                } else {
                    // 其他情况直接完成
                    orderUpdateLqw.set("order_status", OrderStatusEnum.COMPLETE.getKey());
                    isComplete = true;
//                    orderUpdateLqw.set("order_duration", DateUtils.getDateMinDiff(now, gpOrder.getCreateTime()));
                }
            } else if (StringUtils.equals(orderStatus, OrderStatusEnum.COMPLETE.getKey())) {
                returnStr.append("订单").append(gpOrder.getFormCode()).append("已完成，无需继续操作;");
                continue;
            }
            // 获取最近的跟进记录
            orderFlow = this.getOne(new QueryWrapper<GpOrderFlow>().eq("order_id", id).eq("del_status", YesNoEnum.NO.getKey()).orderByDesc("create_time").last("limit 1"));
            if (orderFlow == null) {
                // 没有最近的跟进记录
                // 流入时间设置为订单接入时间
                inletTime = gpOrder.getCreateTime();
            } else {
                // 流入时间设置为上个节点处理时间
                inletTime = orderFlow.getProcessingTime();
            }
            if (flowConfig == null) {
                // 如果没有下一个流转节点，则跳过此条记录
                returnStr.append("订单").append(gpOrder.getFormCode()).append("已完成，无需继续操作;");
                continue;
            }
            // 查看下一步的权限（角色）
            flowConfigRoleRelaList = gpFlowConfigRoleRelaService.listVo(new QueryWrapper<GpFlowConfigRoleRela>().eq("config_id", flowConfig.getId()).eq("del_status", YesNoEnum.NO.getKey()));
            configRoleList = flowConfigRoleRelaList.stream().map(GpFlowConfigRoleRelaVo::getRoleId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(configRoleList) || CollectionUtils.isEmpty(roleList)) {
                returnStr.append("当前用户无法对订单").append(gpOrder.getFormCode()).append("进行【").append(flowConfig.getName()).append("】操作;");
                continue;
            } else {
                configRoleList.retainAll(roleList);
                if (CollectionUtils.isEmpty(configRoleList)) {
                    returnStr.append("当前用户无法对订单").append(gpOrder.getFormCode()).append("进行【").append(flowConfig.getName()).append("】操作;");
                    continue;
                }
            }
            // 生成此次操作的跟进记录
            String saveOrderFlowStr = saveOrderFlow(gpOrderFlowUpdate, gpOrder, orderUpdateLqw, inletTime, now, flowConfig, id, false, isComplete);
            if (StringUtils.isNotBlank(saveOrderFlowStr)) {
                returnStr.append(saveOrderFlowStr);
            }
            // 给下一个流程的员工发送消息通知
//            sendNotifyToNext(flowConfig, gpOrder.getId(), gpOrder.getOrderCharacteristics(), gpOrder.getOrderStatus());
        }
        return returnStr.toString();
    }

    @Override
    @Transactional
    public String withdraw(GpOrderFlowUpdate gpOrderFlowUpdate) {
        StringBuilder returnStr = new StringBuilder();
        GpOrder gpOrder;
        UpdateWrapper<GpOrder> lqw;
        for (Long id : gpOrderFlowUpdate.getIds()) {
            lqw = new UpdateWrapper<>();
            lqw.set("order_duration", null);
            lqw.set("overdue_duration", null);
            // 获取订单信息
            gpOrder = gpOrderService.getById(id);
            if (gpOrder == null || StringUtils.equals(gpOrder.getOrderStatus(), OrderStatusEnum.TO_BE_PICKING_UP_GOODS.getKey())) {
                // 订单不存在或未操作过，跳过当前订单
                continue;
            }
            lqw.eq("id", id);
            List<GpOrderFlow> orderFlowList = this.list(new QueryWrapper<GpOrderFlow>()
                    .eq("del_status", YesNoEnum.NO.getKey())
                    .eq("order_id", id)
                    .orderByDesc("create_time"));
            if (CollectionUtils.isEmpty(orderFlowList)) {
                // 如果没有流转记录，直接撤回到最初的‘待拿货’状态
                lqw.set("order_status", OrderStatusEnum.TO_BE_PICKING_UP_GOODS.getKey());
            } else {
                // 如果有流转记录，删除最近的一次流转记录，并将订单状态修改成上上次的订单状态
                this.removeById(orderFlowList.get(0).getId());
                if (orderFlowList.size() > 1) {
                    GpFlowConfig gpFlowConfig = gpFlowConfigService.getById(orderFlowList.get(1).getConfigId());
                    if (gpFlowConfig != null) {
                        if (StringUtils.equals(gpOrder.getOrderCharacteristics(), OrderCharacteristicsEnum.LOOSE_SHEAR.getKey()) && gpFlowConfig.getSort() == 10) {
                            // 如果是散剪并且上一步是拿货，流转到待发货
                            lqw.set("order_status", OrderStatusEnum.TO_BE_SEND_OUT_GOODS.getKey());
                        } else {
                            lqw.set("order_status", gpFlowConfig.getSort());
                        }
                    } else {
                        // 如果上上次流转记录，直接撤回到最初的‘待拿货’状态
                        lqw.set("order_status", OrderStatusEnum.TO_BE_PICKING_UP_GOODS.getKey());
                    }
                } else {
                    // 如果上上次流转记录，直接撤回到最初的‘待拿货’状态
                    lqw.set("order_status", OrderStatusEnum.TO_BE_PICKING_UP_GOODS.getKey());
                }
            }
            gpOrderService.update(lqw);
        }
        return returnStr.toString();
    }

    @Override
    public String transfer(GpOrderFlowUpdate gpOrderFlowUpdate) {
        StringBuilder returnStr = new StringBuilder();
        GpOrder gpOrder;
        UpdateWrapper<GpOrder> lqw;
        GpOrderFlow beforeOrderFlow;
        Date inletTime;
        Date now = new Date();
        GpFlowConfig flowConfig = gpFlowConfigService.getOne(new QueryWrapper<GpFlowConfig>().eq("del_status", YesNoEnum.NO.getKey()).eq("sort", OrderStatusEnum.TO_BE_TRANSFER.getKey()).last("limit 1"));
        for (Long id : gpOrderFlowUpdate.getIds()) {
            lqw = new UpdateWrapper<>();
            lqw.set("order_duration", null);
            lqw.set("overdue_duration", null);
            lqw.set("order_status", OrderStatusEnum.TO_BE_TRANSFER.getKey());
            // 获取订单信息
            gpOrder = gpOrderService.getById(id);
            if (gpOrder == null) {
                // 订单不存在，跳过当前订单
                continue;
            }
            if (StringUtils.equals(gpOrder.getIsException().toString(), YesNoEnum.YES.getKey())) {
                // 订单状态异常，无法进行流程流转
                returnStr.append("订单").append(gpOrder.getFormCode()).append("异常，请联系录入人员进行操作;");
                continue;
            }
            lqw.eq("id", id);

            // 获取最近的跟进记录
            beforeOrderFlow = this.getOne(new QueryWrapper<GpOrderFlow>().eq("order_id", id).eq("del_status", YesNoEnum.NO.getKey()).orderByDesc("create_time").last("limit 1"));
            if (beforeOrderFlow == null) {
                inletTime = gpOrder.getCreateTime();
            } else {
                inletTime = beforeOrderFlow.getProcessingTime();
            }
            String saveOrderFlowStr = saveOrderFlow(gpOrderFlowUpdate, gpOrder, lqw, inletTime, now, flowConfig, id, true, false);
            if (StringUtils.isNotBlank(saveOrderFlowStr)) {
                returnStr.append(saveOrderFlowStr);
            }
        }
        return returnStr.toString();
    }

    private String saveOrderFlow(GpOrderFlowUpdate gpOrderFlowUpdate, GpOrder gpOrder, UpdateWrapper<GpOrder> lqw, Date inletTime, Date now, GpFlowConfig flowConfig, Long id, boolean isTransfer, boolean isComplete) {
        GpOrderFlow gpOrderFlow = new GpOrderFlow();
        SysUser sysUser = sysUserMapper.selectUserById(gpOrderFlowUpdate.getUserId());
        if (sysUser != null) {
            SysDept sysDept = sysDeptMapper.selectDeptById(sysUser.getDeptId());
            if (sysDept != null) {
                gpOrderFlow.setDeptIds(sysDept.getAncestors() + "," + sysDept.getDeptId());
            }
        }
        if (CollectionUtils.isNotEmpty(gpOrderFlowUpdate.getAnnexList())) {
            gpOrderFlow.setAnnex(String.join(",", gpOrderFlowUpdate.getAnnexList()));
        }
        gpOrderFlow.setStatus(gpOrderFlowUpdate.getStatus());
        gpOrderFlow.setOrderId(id);
        gpOrderFlow.setUserId(gpOrderFlowUpdate.getUserId());
        gpOrderFlow.setDestinationType(gpOrderFlowUpdate.getDestinationType());
        gpOrderFlow.setDestinationNo(gpOrderFlowUpdate.getDestinationNo());
        gpOrderFlow.setOverdueDuration(0L);
        if (gpOrder.getSuspendEndTime() != null) {
            inletTime = gpOrder.getSuspendEndTime();
            lqw.set("suspend_start_time", null);
            lqw.set("suspend_end_time", null);
            lqw.set("suspend_duration", 0);
        }
        gpOrderFlow.setInletTime(inletTime);
        if (gpOrderFlowUpdate.getProcessingTime() == null) {
            gpOrderFlow.setProcessingTime(now);
        } else {
            now = gpOrderFlowUpdate.getProcessingTime();
            gpOrderFlow.setProcessingTime(gpOrderFlowUpdate.getProcessingTime());
        }
        long processingDuration = DateUtils.getDateMinDiff(now, inletTime);
        // 如果是拿货/备货，并且在流入时间<休息结束时间<完成时间，则完成时长需要减掉对应的休息时间
        if (StringUtils.equals(gpOrder.getOrderStatus(), OrderStatusEnum.TO_BE_PICKING_UP_GOODS.getKey())
                || StringUtils.equals(gpOrder.getOrderStatus(), OrderStatusEnum.TO_BE_STOCK_UP.getKey())) {
            long restDuration = extendTime(inletTime, gpOrderFlow.getProcessingTime());
            processingDuration -= restDuration;
        }
        if (isTransfer) {
            // 如果是中转扫一扫，不计算时效
            gpOrderFlow.setProcessingDuration(0L);
        } else {
            /*if (StringUtils.isNotBlank(gpOrderFlowUpdate.getDestinationNo())) {
                // 判断订单流转是否跨天
                LocalDate inletDate = inletTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                LocalDate processingDate = gpOrderFlow.getProcessingTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                long daysDiff = ChronoUnit.DAYS.between(inletDate, processingDate);
                // 判断所选车次是否已发车
                // 获取完成时间是星期几
                Calendar todayCalendar = Calendar.getInstance();
                todayCalendar.setTime(gpOrderFlow.getProcessingTime());
                int todayOfWeek = todayCalendar.get(Calendar.DAY_OF_WEEK); // 1 表示星期日，2 表示星期一，以此类推
                LocalTime processingLocalTime = gpOrderFlow.getProcessingTime().toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
                // 获取今天的车次
                List<GpDestinationNoConfig> todayDestinationNoConfigList;
                if (todayOfWeek == 1 || todayOfWeek == 2) {
                    todayDestinationNoConfigList = gpDestinationNoConfigService.list(new QueryWrapper<GpDestinationNoConfig>()
                            .eq("del_status", YesNoEnum.NO.getKey())
                            .isNotNull("time_slot_two")
                            .orderByAsc("time_slot_two"));
                } else {
                    todayDestinationNoConfigList = gpDestinationNoConfigService.list(new QueryWrapper<GpDestinationNoConfig>()
                            .eq("del_status", YesNoEnum.NO.getKey())
                            .isNotNull("time_slot_one")
                            .orderByAsc("time_slot_one"));
                }
                if (daysDiff == 0) {
                    // 没有跨天，获取当天的车次判断是否超期
                    // 获取流入时间是星期几
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(inletTime);
                    int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); // 1 表示星期日，2 表示星期一，以此类推
                    // 获取流入时间时分秒
                    LocalTime inletLocalTime = inletTime.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
                    List<GpDestinationNoConfig> destinationNoConfigList = this.getResidueDestinationNo(dayOfWeek, inletLocalTime);
                    if (CollectionUtils.isEmpty(destinationNoConfigList)) {
                        gpOrderFlow.setOverdueDuration(0L);
                    }
                    // 判断流程是否超期
                    boolean haveDestinationNo = isHaveDestinationNo(gpOrderFlowUpdate.getDestinationNo(), flowConfig.getRedDuration(), gpOrderFlow, processingDuration, dayOfWeek, inletLocalTime, destinationNoConfigList);
                    if (!haveDestinationNo) {
                        gpOrderFlow.setOverdueDuration(0L);
                    }
                } else if (daysDiff == 1) {
                    // 相差一天，获取流入当天剩余的车次
                    // 获取流入时间是星期几
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(inletTime);
                    int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); // 1 表示星期日，2 表示星期一，以此类推
                    // 获取流入时间时分秒
                    LocalTime inletLocalTime = inletTime.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
                    // 流入当天剩余的车次
                    List<GpDestinationNoConfig> yesterdayDestinationNo = this.getResidueDestinationNo(dayOfWeek, inletLocalTime);
                    if (CollectionUtils.isEmpty(yesterdayDestinationNo)) {
                        // 如果流入当天没有剩余的车次，则计算超时从今天第一个车次开始计算
                        if (StringUtils.equals(todayDestinationNoConfigList.get(0).getDestinationNo(), gpOrderFlowUpdate.getDestinationNo())) {
                            // 如果所选车次为今天的第一班车，则未超期
                            gpOrderFlow.setOverdueDuration(0L);
                        } else {
                            // 超期
                            if (flowConfig.getRedDuration() < processingDuration) {
                                gpOrderFlow.setOverdueDuration(processingDuration - flowConfig.getRedDuration());
                            }
                        }
                    } else if (yesterdayDestinationNo.size() == 1 && StringUtils.equals(todayDestinationNoConfigList.get(0).getDestinationNo(), gpOrderFlowUpdate.getDestinationNo())) {
                        // 如果流入当天剩余一班且超时时间大于发车时间，且选择车次为今天的第一班车，则未超期
                        LocalTime estimatedCompletionTime = null;
                        LocalTime timeSlot = null;
                        if (dayOfWeek == 1 || dayOfWeek == 2) {
                            estimatedCompletionTime = inletLocalTime.plusMinutes(yesterdayDestinationNo.get(0).getOverdueDurationTwo());
                            timeSlot = yesterdayDestinationNo.get(0).getTimeSlotTwo().toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
                        } else {
                            estimatedCompletionTime = inletLocalTime.plusMinutes(yesterdayDestinationNo.get(0).getOverdueDurationOne());
                            timeSlot = yesterdayDestinationNo.get(0).getTimeSlotOne().toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
                        }
                        if (estimatedCompletionTime.compareTo(timeSlot) > 0) {
                            gpOrderFlow.setOverdueDuration(0L);
                        } else {
                            gpOrderFlow.setOverdueDuration(processingDuration - flowConfig.getRedDuration());
                        }
                    } else {
                        // 其它情况均为超时
                        if (flowConfig.getRedDuration() < processingDuration) {
                            gpOrderFlow.setOverdueDuration(processingDuration - flowConfig.getRedDuration());
                        }
                    }
                } else {
                    // 相差大于一天均为超时
                    if (flowConfig.getRedDuration() < processingDuration) {
                        gpOrderFlow.setOverdueDuration(processingDuration - flowConfig.getRedDuration());
                    }
                }
            } else {
                if (flowConfig.getRedDuration() < processingDuration) {
                    gpOrderFlow.setOverdueDuration(processingDuration - flowConfig.getRedDuration());
                }
            }*/
            // 如果有选车次，时效计算按发车时间计算，如果计算出来时负数的改成0
            if (StringUtils.isNotBlank(gpOrderFlowUpdate.getDestinationNo())) {
                GpDestinationNoLog gpDestinationNoLog = gpDestinationNoLogService.getOne(new LambdaQueryWrapper<GpDestinationNoLog>()
                        .eq(GpDestinationNoLog::getDelStatus, YesNoEnum.NO.getKey())
                        .eq(GpDestinationNoLog::getDestinationNo, gpOrderFlowUpdate.getDestinationNo())
                        .last("AND DATE(departure_time) = DATE(NOW()) limit 1"));
                if (gpDestinationNoLog == null) {
                    return "订单" + gpOrder.getFormCode() + "所选车次未发车，请发车后再进行相应操作;";
                }
                processingDuration = DateUtils.getDateMinDiff(gpDestinationNoLog.getDepartureTime(), inletTime);
                if (processingDuration < 0) {
                    processingDuration = 0;
                }
            }
            gpOrderFlow.setProcessingDuration(processingDuration);
            Long redDuration = 0L;
            // TODO:LEE 散剪和大货流转时间区分先不开启，等前端将配置接上去再开
            redDuration = flowConfig.getRedDuration();
            if (StringUtils.equals(gpOrder.getOrderCharacteristics(), OrderCharacteristicsEnum.LOOSE_SHEAR.getKey())) {
                redDuration = flowConfig.getRedDuration();
            }else {
                redDuration = flowConfig.getBigRedDuration();
            }
            if (redDuration < processingDuration) {
                gpOrderFlow.setOverdueDuration(processingDuration - redDuration);
            }
        }
        gpOrderFlow.setConfigId(flowConfig.getId());
        gpOrderFlow.setConfigName(flowConfig.getName());
        gpOrderFlow.setRemarks(gpOrderFlowUpdate.getRemarks());
        gpOrderFlow.setProcessingOpinion(gpOrder.getVersion().toString());
        if (isComplete) {
            Long orderDuration = this.getTotalDuration(gpOrder.getId());
            lqw.set("order_duration", orderDuration + processingDuration);
        }
        boolean update = gpOrderService.update(lqw);
        if (!update) {
            return null;
        }
        this.save(gpOrderFlow);
        return null;
    }

    /**
     * 获取流入当天剩余的车次
     * @param dayOfWeek 流入时间（周几）
     * @param inletLocalTime 流入时间
     * @return
     */
    private List<GpDestinationNoConfig> getResidueDestinationNo(int dayOfWeek, LocalTime inletLocalTime) {
        // 如果有传去向车次，获取订单可用车次信息（发车时间>流入时间的车次）
        List<GpDestinationNoConfig> destinationNoConfigList;
        if (dayOfWeek == 1 || dayOfWeek == 2) {
            destinationNoConfigList = gpDestinationNoConfigService.list(new QueryWrapper<GpDestinationNoConfig>()
                    .gt("time_slot_two", inletLocalTime)
                    .eq("del_status", YesNoEnum.NO.getKey())
                    .orderByAsc("time_slot_two"));
        } else {
            destinationNoConfigList = gpDestinationNoConfigService.list(new QueryWrapper<GpDestinationNoConfig>()
                    .gt("time_slot_one", inletLocalTime)
                    .eq("del_status", YesNoEnum.NO.getKey())
                    .orderByAsc("time_slot_one"));
        }
        return destinationNoConfigList;
    }

    /**
     * 判断所选车次是否超期
     * @param destinationNo 所选车次
     * @param redDuration 预计完成时长
     * @param gpOrderFlow 流转记录（设置超期时长）
     * @param processingDuration 完成时长
     * @param dayOfWeek 流入时间（周几）
     * @param inletLocalTime 流入时间
     * @param destinationNoConfigList 可选车次列表
     * @return
     */
    private boolean isHaveDestinationNo(String destinationNo, Long redDuration, GpOrderFlow gpOrderFlow, long processingDuration, int dayOfWeek, LocalTime inletLocalTime, List<GpDestinationNoConfig> destinationNoConfigList) {
        boolean haveDestinationNo = false;
        GpDestinationNoConfig gpDestinationNoConfig;
        LocalTime estimatedCompletionTime = null;
        LocalTime timeSlot = null;
        for (int i = 0; i < destinationNoConfigList.size(); i++) {
            gpDestinationNoConfig = destinationNoConfigList.get(i);
            // 计算预计完成时间
            if (i == 0) {
                if (dayOfWeek == 1 || dayOfWeek == 2) {
                    estimatedCompletionTime = inletLocalTime.plusMinutes(gpDestinationNoConfig.getOverdueDurationTwo()); // 预计超时时间
                    timeSlot = gpDestinationNoConfig.getTimeSlotTwo().toInstant().atZone(ZoneId.systemDefault()).toLocalTime(); // 发车时间
                } else {
                    estimatedCompletionTime = inletLocalTime.plusMinutes(gpDestinationNoConfig.getOverdueDurationOne()); // 预计超时时间
                    timeSlot = gpDestinationNoConfig.getTimeSlotOne().toInstant().atZone(ZoneId.systemDefault()).toLocalTime(); // 发车时间
                }
            }
            // 判断流程是否超期
            if (StringUtils.equals(gpDestinationNoConfig.getDestinationNo(), destinationNo)) {
                haveDestinationNo = true;
                if (i == 0) {
                    // 如果选择的车次是最近的一个车次，则流程未超期
                    gpOrderFlow.setOverdueDuration(0L);
                } else if (i == 1 && estimatedCompletionTime != null && timeSlot != null && estimatedCompletionTime.compareTo(timeSlot) > 0) {
                    // 如果选择的车次是第二近的车次，并且流程预计完成时间>最近一个车次的发车时间，则流程未超期
                    gpOrderFlow.setOverdueDuration(0L);
                } else {
                    // 其他情况流程超期，超期时长=完成时间-预计完成时间
                    gpOrderFlow.setOverdueDuration(processingDuration - redDuration);
                }
                break;
            }
        }
        return haveDestinationNo;
    }

    private long extendTime(Date inletTime, Date processingTime) {
        long returnDuration = 0;
        LocalTime noonStartTime = LocalTime.of(12, 30, 0); // 中午休息开始时间：12:30:00
        LocalTime noonEndTime = LocalTime.of(13, 0, 0); // 中午休息结束时间：13:00:00
        long noonDuration = Duration.between(noonStartTime, noonEndTime).toMinutes(); // 中午休息时长
        LocalTime nightStartTime = LocalTime.of(18, 30, 0); // 晚上休息开始时间：18:30:00
        LocalTime nightEndTime = LocalTime.of(19, 0, 0); // 晚上休息结束时间：19:00:00
        long nightDuration = Duration.between(nightStartTime, nightEndTime).toMinutes(); // 晚上休息时长
        // 流入时间
        Instant inletInstant = inletTime.toInstant();
        LocalTime inletLocalTime = inletInstant.atZone(ZoneId.systemDefault()).toLocalTime();
        // 预计完成时间
        Instant processingInstant = processingTime.toInstant();
        LocalTime processingLocalTime = processingInstant.atZone(ZoneId.systemDefault()).toLocalTime();
        if (inletLocalTime.compareTo(noonEndTime) < 0 && processingLocalTime.compareTo(noonEndTime) > 0) {
            // 实际休息时长=休息结束时间-流入时间（如果休息时间比中午休息时长长，则使用中午休息时长）
            long restDuration = Duration.between(inletLocalTime, noonEndTime).toMinutes();
            if (restDuration > noonDuration) {
                returnDuration += noonDuration;
            } else {
                returnDuration += restDuration;
            }
        }
        if (inletLocalTime.compareTo(nightEndTime) < 0 && processingLocalTime.compareTo(nightEndTime) > 0) {
            // 实际休息时长=休息结束时间-流入时间（如果休息时间比晚上休息时长长，则使用晚上休息时长）
            long restDuration = Duration.between(inletLocalTime, nightEndTime).toMinutes();
            if (restDuration > nightDuration) {
                returnDuration += nightDuration;
            } else {
                returnDuration += restDuration;
            }
        }
        return returnDuration;
    }

    /**
     * 给下一个流程的员工发送消息通知
     */
    private void sendNotifyToNext(GpFlowConfig flowConfig, Long orderId, String orderCharacteristics, String orderStatus) {
        if (flowConfig != null) {
            // 获取下一个流转节点
            if (StringUtils.equals(orderCharacteristics, OrderCharacteristicsEnum.LOOSE_SHEAR.getKey()) && StringUtils.equals(orderStatus, OrderStatusEnum.TO_BE_SEND_OUT_GOODS.getKey())) {
                // 如果是散剪，并且订单状态是拿货，则跳过备货，直接到送货
                flowConfig = gpFlowConfigService.getOne(new QueryWrapper<GpFlowConfig>().gt("sort", flowConfig.getSort()).eq("del_status", YesNoEnum.NO.getKey()).orderByAsc("sort").last("limit 1,1"));
            } else {
                flowConfig = gpFlowConfigService.getOne(new QueryWrapper<GpFlowConfig>().gt("sort", flowConfig.getSort()).eq("del_status", YesNoEnum.NO.getKey()).orderByAsc("sort").last("limit 1"));
            }
            gpOrderNotifyService.sendNotifyByConfigId(flowConfig.getId(), orderId);
        }
    }

    @Override
    public List<FormsVo> forms(String userId, String deptId, String type, String organiseUnit, String startTime, String endTime) {
        List<FormsVo> formsVoList = new ArrayList<>();
        FormsVo formsVo = new FormsVo();
        if (StringUtils.isNotBlank(deptId)) {
            formsVo =  this.baseMapper.deptFormVo(deptId, type, userId, organiseUnit, startTime, endTime);
            formsVo.setTotalCompleteOrderNum(this.baseMapper.getTotalCompleteOrderNum(deptId, type, userId, organiseUnit, startTime, endTime));
            formsVo.setDetailsList(this.baseMapper.deptFormDetailsList(deptId, type, userId, organiseUnit, startTime, endTime));
        } else if (StringUtils.isNotBlank(userId)) {
            formsVo = this.baseMapper.userFormVo(userId, type, organiseUnit, startTime, endTime);
            formsVo.setDetailsList(this.baseMapper.userFormDetailsList(userId, type, organiseUnit, startTime, endTime));
        }
        formsVoList.add(formsVo);
        return formsVoList;
    }

    @Override
    public AjaxResult add(GpOrderFlowUpdate gpOrderFlowUpdate) {
        StringBuilder returnStr = new StringBuilder();
        GpOrderFlow gpOrderFlow;
        GpOrder gpOrder;
        Date inletTime = new Date();
        // 查看当前用户所有的权限（角色）
        List<Long> roleList = sysUserRoleMapper.getroleIdListByUserId(gpOrderFlowUpdate.getUserId().toString());
        List<GpFlowConfigRoleRelaVo> flowConfigRoleRelaList;
        List<Long> configRoleList;
        // 获取订单信息
        Long id = gpOrderFlowUpdate.getId();
        gpOrder = gpOrderService.getById(id);
        if (gpOrder == null) {
            return AjaxResult.error("订单不存在");
        }
        GpFlowConfig flowConfig = gpFlowConfigService.getById(gpOrderFlowUpdate.getConfigId());
        if (flowConfig == null) {
            return AjaxResult.error("流转节点不存在");
        }
        gpOrder.setOrderStatus(flowConfig.getSort().toString());
        if (StringUtils.isNotBlank(gpOrderFlowUpdate.getDestinationType())) {
            if (StringUtils.equals(gpOrderFlowUpdate.getDestinationType(), DestinationTypeEnum.TRANSIT_WAREHOUSE.getKey())) {
                // 中转(待中转)
                gpOrder.setOrderStatus(OrderStatusEnum.TO_BE_TRANSFER.getKey());
            } else {
                // 发货（完成）
                gpOrder.setOrderStatus(OrderStatusEnum.COMPLETE.getKey());
            }
        }
        // 如果订单状态修改为完成，则设置订单时长
        if (StringUtils.equals(gpOrder.getOrderStatus(), OrderStatusEnum.COMPLETE.getKey())) {
            gpOrder.setOrderDuration(DateUtils.getDateMinDiff(new Date(), gpOrder.getCreateTime()));
        }
        gpOrderService.updateById(gpOrder);
        // 查看下一步的权限（角色）
        flowConfigRoleRelaList = gpFlowConfigRoleRelaService.listVo(new QueryWrapper<GpFlowConfigRoleRela>().eq("config_id", flowConfig.getId()).eq("del_status", YesNoEnum.NO.getKey()));
        configRoleList = flowConfigRoleRelaList.stream().map(GpFlowConfigRoleRelaVo::getRoleId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(configRoleList) || CollectionUtils.isEmpty(roleList)) {
            returnStr.append("当前用户无法对订单").append(gpOrder.getFormCode()).append("进行【").append(flowConfig.getName()).append("】操作;");
        } else {
            configRoleList.retainAll(roleList);
            if (CollectionUtils.isEmpty(configRoleList)) {
                returnStr.append("当前用户无法对订单").append(gpOrder.getFormCode()).append("进行【").append(flowConfig.getName()).append("】操作;");
            }
        }
        // 生成此次操作的跟进记录
        gpOrderFlow = new GpOrderFlow();
        SysUser sysUser = sysUserMapper.selectUserById(gpOrderFlowUpdate.getUserId());
        if (sysUser != null) {
            SysDept sysDept = sysDeptMapper.selectDeptById(sysUser.getDeptId());
            if (sysDept != null) {
                gpOrderFlow.setDeptIds(sysDept.getAncestors() + "," + sysDept.getDeptId());
            }
        }
        gpOrderFlow.setOrderId(id);
        gpOrderFlow.setUserId(gpOrderFlowUpdate.getUserId());
        gpOrderFlow.setDestinationType(gpOrderFlowUpdate.getDestinationType());
        gpOrderFlow.setDestinationNo(gpOrderFlowUpdate.getDestinationNo());
        gpOrderFlow.setOverdueDuration(0L);
        gpOrderFlow.setInletTime(inletTime);
        Date now = new Date();
        if (gpOrderFlowUpdate.getProcessingTime() == null) {
            gpOrderFlow.setProcessingTime(now);
        } else {
            now = gpOrderFlowUpdate.getProcessingTime();
            gpOrderFlow.setProcessingTime(gpOrderFlowUpdate.getProcessingTime());
        }
        long processingDurationSecond = DateUtils.getDateSecondDiff(now, inletTime);
        long processingDuration = BigDecimal.valueOf(processingDurationSecond).divide(BigDecimal.valueOf(60), 0, RoundingMode.CEILING).longValue();
        gpOrderFlow.setProcessingDuration(processingDuration);
        gpOrderFlow.setConfigId(flowConfig.getId());
        gpOrderFlow.setConfigName(flowConfig.getName());
        Long redDuration = 0L;
        redDuration = flowConfig.getRedDuration();
        // TODO:LEE 散剪和大货流转时间区分先不开启，等前端将配置接上去再开
        if (StringUtils.equals(gpOrder.getOrderCharacteristics(), OrderCharacteristicsEnum.LOOSE_SHEAR.getKey())) {
            redDuration = flowConfig.getRedDuration();
        }else {
            redDuration = flowConfig.getBigRedDuration();
        }
        if (redDuration < processingDuration) {
            gpOrderFlow.setOverdueDuration(processingDuration - redDuration);
        }
        gpOrderFlow.setRemarks(gpOrderFlowUpdate.getRemarks());
        this.save(gpOrderFlow);
        return AjaxResult.success();
    }

    @Override
    public List<EfficiencyVo> efficiency(String deptId, String startTime, String endTime) {
        List<EfficiencyVo> list = new ArrayList<>();
        EfficiencyVo looseShear = this.baseMapper.looseShearEfficiency(deptId, startTime, endTime);
        looseShear.setType("散剪");
        // 获取散剪录入订单数
        looseShear.setEnterNum(this.baseMapper.looseShearEnterNum(startTime, endTime));
        // 获取散剪未完成订单数
        looseShear.setRemainNum(this.baseMapper.looseShearRemainNum(startTime, endTime));
        efficiencyCount(looseShear);
        list.add(looseShear);

        // 拿货
        EfficiencyVo pickingUpGoods = this.baseMapper.deptEfficiency(OrderStatusEnum.TO_BE_STOCK_UP.getKey(), deptId, startTime, endTime, OrderCharacteristicsEnum.BIG.getKey());
        pickingUpGoods.setType("拿货");
        // 获取大货录入订单数
        Long bigEnterNum = this.baseMapper.deptEnterNum(startTime, endTime, OrderCharacteristicsEnum.BIG.getKey());
        // 获取大货+散剪录入订单数
        Long allEnterNum = this.baseMapper.deptEnterNum(startTime, endTime, null);
        pickingUpGoods.setEnterNum(bigEnterNum);
        // 获取拿货未完成订单数
        pickingUpGoods.setRemainNum(this.baseMapper.deptRemainNum(OrderStatusEnum.TO_BE_STOCK_UP.getKey(), startTime, endTime, OrderCharacteristicsEnum.BIG.getKey()));
        efficiencyCount(pickingUpGoods);
        list.add(pickingUpGoods);

        // 备货
        EfficiencyVo stockUpGoods = this.baseMapper.deptEfficiency(OrderStatusEnum.TO_BE_SEND_OUT_GOODS.getKey(), deptId, startTime, endTime, OrderCharacteristicsEnum.BIG.getKey());
        stockUpGoods.setType("备货");
        // 获取备货录入订单数
        stockUpGoods.setEnterNum(bigEnterNum);
        // 获取备货未完成订单数
        stockUpGoods.setRemainNum(this.baseMapper.deptRemainNum(OrderStatusEnum.TO_BE_SEND_OUT_GOODS.getKey(), startTime, endTime, OrderCharacteristicsEnum.BIG.getKey()));
        efficiencyCount(stockUpGoods);
        list.add(stockUpGoods);

        // 仓库发货
        EfficiencyVo sendOutGoods = this.baseMapper.deptEfficiency(null, deptId, startTime, endTime, null);
        sendOutGoods.setType("仓库发货");
        // 获取仓库发货录入订单数
        sendOutGoods.setEnterNum(allEnterNum);
        // 获取仓库发货未完成订单数
        sendOutGoods.setRemainNum(this.baseMapper.deptRemainNum(null, startTime, endTime, null));
        efficiencyCount(sendOutGoods);
        list.add(sendOutGoods);

        // 中转发货
        EfficiencyVo transferGoods = this.baseMapper.deptEfficiency(OrderStatusEnum.TRANSFER.getKey(), deptId, startTime, endTime, null);
        transferGoods.setType("中转发货");
        // 获取散剪录入订单数
        transferGoods.setEnterNum(this.baseMapper.transferEnterNum(startTime, endTime));
        // 获取散剪未完成订单数
        transferGoods.setRemainNum(this.baseMapper.transferRemainNum(startTime, endTime));
        efficiencyCount(transferGoods);
        list.add(transferGoods);
        return list;
    }

    @Override
    public List<OrderQuantityVo> orderQuantityStatistics(String deptId,List<SysUser> sysUsers, String orderStatus, String startTime, String endTime) {
        List<OrderQuantityVo> list = new ArrayList<>();
        OrderQuantityVo orderQuantityVo;
        List<OrderQuantityDayVo> days;
        // 计算每个人的单量
        for (SysUser sysUser : sysUsers) {
            orderQuantityVo = new OrderQuantityVo();
            // 获取每天单量数据
            days = this.baseMapper.getOrderQuantityDayVoList(deptId, sysUser.getUserId(), orderStatus, startTime, endTime);
            // 单量统计数据填充
            this.initOrderQuantity(orderQuantityVo, days, sysUser);
            list.add(orderQuantityVo);
        }
        // 计算单量合计
        days = this.baseMapper.getOrderQuantityDayVoList(deptId, null, orderStatus, startTime, endTime);
        orderQuantityVo = new OrderQuantityVo();
        orderQuantityVo.setUserName("总计");
        // 单量统计数据填充
        this.initOrderQuantity(orderQuantityVo, days, null);
        list.add(orderQuantityVo);
        return list;
    }

    @Override
    public List<SysUser> selectUserList(String deptId, String orderStatus, String startTime, String endTime) {
        return this.baseMapper.selectUserList(deptId, orderStatus, startTime, endTime);
    }

    @Override
    public String getFlowStatus(QueryWrapper<GpOrderFlow> lqw) {
        return this.baseMapper.getFlowStatus(lqw);
    }


    @Override
    public String getFlowStatusHistory(QueryWrapper<GpOrderFlow> lqw) {
        return this.baseMapper.getFlowStatusHistory(lqw);
    }


    @Override
    public String getAnnexList(QueryWrapper<GpOrderFlow> lqw) {
        return this.baseMapper.getAnnexList(lqw);
    }

    private void initOrderQuantity(OrderQuantityVo orderQuantityVo, List<OrderQuantityDayVo> days, SysUser sysUser) {
        Long totalCompleteOrderNum = 0L;
        BigDecimal attendanceDays = BigDecimal.ZERO;
        for (OrderQuantityDayVo day : days) {
            totalCompleteOrderNum += day.getOrderNum();
            if (day.getMorningNum() > 0) {
                attendanceDays = attendanceDays.add(BigDecimal.valueOf(0.5));
            }
            if (day.getAfternoonNum() > 0) {
                attendanceDays = attendanceDays.add(BigDecimal.valueOf(0.5));
            }
        }
        if (sysUser != null) {
            orderQuantityVo.setUserId(sysUser.getUserId());
            orderQuantityVo.setUserName(sysUser.getNickName());
        }
        orderQuantityVo.setOrderQuantityDayList(days);
        orderQuantityVo.setTotalCompleteOrderNum(totalCompleteOrderNum);
        orderQuantityVo.setAttendanceDays(attendanceDays);
        if (attendanceDays.compareTo(BigDecimal.ZERO) == 0) {
            orderQuantityVo.setDailyCompletedOrdersAvg(BigDecimal.ZERO);
        } else {
            orderQuantityVo.setDailyCompletedOrdersAvg(BigDecimal.valueOf(totalCompleteOrderNum).divide(attendanceDays, 0, RoundingMode.HALF_UP));
        }
    }

    private void efficiencyCount(EfficiencyVo looseShear) {
        // 按时完成率 = 按时完成数量 * 100 / 总完成单量
        if (looseShear.getTotalCompleteOrderNum() == 0L) {
            looseShear.setFinishOnTimeRate(BigDecimal.ZERO);
        } else {
            looseShear.setFinishOnTimeRate(BigDecimal.valueOf(looseShear.getFinishOnTimeNum())
                    .multiply(BigDecimal.valueOf(100))
                    .divide(BigDecimal.valueOf(looseShear.getTotalCompleteOrderNum()), 2, RoundingMode.HALF_UP));
        }
        // 平均超时时长 = 超期总时长 / 超期完成数量
        if (looseShear.getTimedOutNum() == 0L) {
            looseShear.setTimedOutDurationAvg(BigDecimal.ZERO);
        } else {
            looseShear.setTimedOutDurationAvg(BigDecimal.valueOf(looseShear.getTimedOutDurationSum()).divide(BigDecimal.valueOf(looseShear.getTimedOutNum()), 2, RoundingMode.HALF_UP));
        }
    }

    /**
     * 获取订单所有流程的总时长
     * @param orderId
     * @return
     */
    @Override
    public Long getTotalDuration(Long orderId) {
        return this.baseMapper.getTotalDuration(orderId);
    }
}
